using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.ComponentModel;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using ZedGraph;

#if HAS_MSCHART
using System.Windows.Forms.DataVisualization.Charting;
#endif

[DesignerCategory("Code")]
public class ProgressionDialog : Form
{
    IContainer components = null;
    public ProgressBar progressBar1;
    public Button Abort, closeButton;
    private MyZedGraph zg1;
    public List<FileSystemInfo> files;
    public string targetName, compressie;
    public bool multiProc = true;
    public BackgroundWorker bw;
    public int secondsPassed = 0;
    public ArrayList threadCount = new ArrayList();
    public ArrayList workerThreadCount = new ArrayList();
    int threadoverhead = 0;
    public List<int> timePassed = new List<int>();
    public ArrayList timePassed2 = new ArrayList();
    public System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
    public Pool myThreadPool;
    int threads;
    public SpinnerThread spinnerThreads;

    public class SpinnerThread : NumericUpDown
    {
        public SpinnerThread() : base()
        {
            Location = new Point(12, 210);
            this.Minimum = 1;
            this.Maximum = 100;
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
            components.Dispose();
        
        base.Dispose(disposing);
    }

    public void timer1_Tick(object sender, EventArgs e)
    {
        secondsPassed += 1;
        timePassed.Add(secondsPassed);
        timePassed2.Add(secondsPassed);
        threadCount.Add(Process.GetCurrentProcess().Threads.Count);
        zg1.foo();
        int zeitPassed = timePassed[timePassed.Count - 1];

        if (myThreadPool != null)
        {
            zg1.queue.Add(zeitPassed, myThreadPool._tasks.Count);
            zg1.list2.Add(zeitPassed, myThreadPool.busyWorkers.Count);
            zg1.completedCount.Add(zeitPassed, myThreadPool.completedCount);
            zg1.size.Add(zeitPassed, myThreadPool.intendedSize);

            if (files != null)
                progressBar1.Value = (myThreadPool.completedCount * 100) / files.Count % 101;
        }

        zg1.myRefresh();
    }

    public class MyProgressBar : ProgressBar
    {
        public MyProgressBar()
        {
            Location = new Point(65, 29);
            Name = "progressBar1";
            Size = new Size(355, 23);
            TabIndex = 0;
        }
    }

    private class ButtonAbort : Button
    {
        public ButtonAbort() : base()
        {
            Location = new Point(194, 760);
            Name = "Abort";
            Size = new Size(75, 23);
            TabIndex = 1;
            Text = "Abort";
            UseVisualStyleBackColor = true;
        }
    }

    public void setPoolSize(object sender, EventArgs e)
    {
        myThreadPool.setSize((int)spinnerThreads.Value);
    }

    public ProgressionDialog(int threads = 5)
    {
        this.threads = threads;
        myThreadPool = new Pool(threads);
        var minValue = DateTime.Now.AddSeconds(-3600);
        var maxValue = minValue.AddSeconds(5400);
        progressBar1 = new MyProgressBar();
        Abort = new ButtonAbort();
        closeButton = new MyCloseButton(this);
        SuspendLayout();
        threadoverhead = Process.GetCurrentProcess().Threads.Count;
        threadCount.Add(Process.GetCurrentProcess().Threads.Count);
        timePassed.Add(0);
        spinnerThreads = new SpinnerThread();
        spinnerThreads.Value = myThreadPool.intendedSize;
        spinnerThreads.ValueChanged += new EventHandler(setPoolSize);
        Abort.Click += new EventHandler(this.Abort_Click);
        zg1 = new MyZedGraph();
        zg1.foo();
        Controls.Add(Abort);
        Controls.Add(closeButton);
        Controls.Add(progressBar1);
        Controls.Add(zg1);
        Controls.Add(spinnerThreads);
        Name = "ProgressDialog";
        Text = "ProgressDialog";
        AutoScaleDimensions = new SizeF(6F, 13F);
        AutoScaleMode = AutoScaleMode.Font;
        ClientSize = new Size(640, 800);
        ResumeLayout(false);
        closeButton.Enabled = false;

        timer1.Interval = 1000;
        timer1.Start();
        timer1.Tick += timer1_Tick;
        Process thisProc = Process.GetCurrentProcess();

        if (!multiProc)
            thisProc.ProcessorAffinity = (IntPtr)1;

        
    }

    public void done(object sender, RunWorkerCompletedEventArgs e)
    {
        Abort.Enabled = false;
        closeButton.Enabled = true;
        myThreadPool.quit();
        progressBar1.Value = 100;
        timer1.Stop();
    }

    public class MyCloseButton : Button
    {
        ProgressionDialog parent;

        public MyCloseButton(ProgressionDialog parent) : base()
        {
            this.parent = parent;
            Location = new Point(300, 760);
            Name = "Close";
            Size = new Size(75, 23);
            TabIndex = 2;
            Text = "Close";
            UseVisualStyleBackColor = true;
            Click += new EventHandler(parent.CloseButton_Click);
        }
    }

    


    private void Abort_Click(object sender, EventArgs e)
    {
        Console.Error.WriteLine("Abort");
        Abort.Enabled = false;
        bw.CancelAsync();
        myThreadPool.clearQueue();
    }

    public void CloseButton_Click(object sender, EventArgs e)
    {
        Close();
    }
}

public class CreatingDialog : ProgressionDialog
{
    Stopwatch stopWatch = new Stopwatch();

    public CreatingDialog() : this(5) { }

    public CreatingDialog(int threads) : base(threads)
    {
        stopWatch.Start();
        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(work);
        bw.WorkerSupportsCancellation = true;
        bw.WorkerReportsProgress = true;
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(done);
        bw.ProgressChanged += new ProgressChangedEventHandler(progressie);
        bw.RunWorkerAsync();
    }

    void progressie(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    public string time()
    {
        return stopWatch.Elapsed.ToString();
    }

    public void work(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        ArchiveFactory factory;
        MyList list = new MyList(files);

        if (targetName.Length < 1)
            targetName = "standard";    // Norton Commander stijl

        if (!targetName.EndsWith(".prt"))
            targetName += ".prt";

        if (compressie.Equals("Geen"))
        {
            factory = new ArchiveFactory(worker, myThreadPool);
            factory.createNew(targetName, list.fileNames());
        }
        else if (compressie.Equals("DNGS"))
        {
            factory = new DNGSArchiveFactory(worker, myThreadPool);
            factory.createNew(targetName, list.fileNames());
        }
        else if (compressie.Equals("GZip"))
        {
            factory = new GZipArchiveFactory(worker);
            factory.createNew(targetName, list.fileNames());
        }
        else
        {
            Console.Error.WriteLine("Kies een compressiemethode");
            return;
        }

        Console.Error.WriteLine("Operatie compleet in: {0}", stopWatch.Elapsed);
        stopWatch.Stop();
    }
}

public class TestingDialog : ProgressionDialog
{
    Archive archive;

    public TestingDialog(Archive archive)
    {
        this.archive = archive;
        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(work);
        bw.WorkerSupportsCancellation = true;
        bw.WorkerReportsProgress = true;
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(done);
        bw.ProgressChanged += new ProgressChangedEventHandler(progressie);
        bw.RunWorkerAsync();
    }

    void progressie(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
    }

    public void work(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        if (archive.test2(worker))
            MessageBox.Show("Archief OK");
        else
            MessageBox.Show("Archief verrot");
    }
}

public class ExtractingDialog : ProgressionDialog
{
    Archive archive;
    string targetDir;

    public ExtractingDialog(Archive archive, string targetDir)
    {
        this.archive = archive;
        this.targetDir = targetDir;
        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(work);
        bw.WorkerSupportsCancellation = false;
        bw.WorkerReportsProgress = false;
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(done);
    }

    public void work(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        archive.extract(targetDir);
    }

    public void go()
    {
        bw.RunWorkerAsync();
    }
}

